package com.binc.testspring.common.aspect;

import com.binc.testspring.common.annotation.BincLog;
import com.binc.testspring.dto.SysLogBo;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 自定义注解，配合切面判断插入操作是否重复提交了  处理的切面类
 */

@Aspect  // 使用@Aspect注解声明一个切面
@Component
@Slf4j
public class BincLogAspect {

    //这个的作用是将日志记录到数据库中；类似于项目中的@OperateLogger   我们本机联系的话，就不搞这么复杂了，注解将信息记录到log日志就行了
        // @Autowired
        // private SysLogService sysLogService;

        /**
         * 这里我们使用注解的形式（表示如果标了 BincLog注解的话就是一个切点）
         * 当然，我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
         * 切点表达式:   execution(...)
         */
        @Pointcut("@annotation(com.binc.testspring.common.annotation.BincLog)")
        public void logPointCut() {}

        /**
         * 环绕通知 @Around  ， 当然也可以使用 @Before (前置通知)  @After (后置通知)
         * @param point
         * @return
         * @throws Throwable
         */
        @Around("logPointCut()")
        public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        Object result = point.proceed();
        long time = System.currentTimeMillis() - beginTime;
        try {
            saveLog(point, time);
        } catch (Exception e) {
        }
        return result;
    }

        /**
         * 保存日志
         * @param joinPoint
         * @param time
         */
        private void saveLog(ProceedingJoinPoint joinPoint, long time) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SysLogBo sysLogBO = new SysLogBo();
        //执行时间
        sysLogBO.setExeuTime(time);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        sysLogBO.setCreateDate(dateFormat.format(new Date()));
        BincLog sysLog = method.getAnnotation(BincLog.class);
        if(sysLog != null){
            //注解上的描述
            sysLogBO.setRemark(sysLog.value());
        }
        //请求的 类名、方法名  【切面方法的类名  方法名】
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLogBO.setClassName(className);
        sysLogBO.setMethodName(methodName);
        //请求的参数  【切面方法的形参】
        Object[] args = joinPoint.getArgs();
        try{
            List<String> list = new ArrayList<String>();
            for (Object o : args) {
                list.add(new Gson().toJson(o));
            }
            sysLogBO.setParams(list.toString());
        }catch (Exception e){ }
        //这里就不直接存库了，我们改成本地log4j记录
        //sysLogService.save(sysLogBO);
            log.info(sysLogBO.toString());
    }

    }
